home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Camelot / Camelot 105 (1991-02)(Swedish User Group of Amiga)(SE)(PD)[WB].zip / Camelot 105 (1991-02)(Swedish User Group of Amiga)(SE)(PD)[WB].adf / AmigaUUCP / dnews / group.c < prev    next >
C/C++ Source or Header  |  1991-02-02  |  9KB  |  546 lines

  1.  
  2. /*
  3.  *  GROUP.C
  4.  *
  5.  */
  6.  
  7. #include "defs.h"
  8.  
  9. Prototype void LoadGroups(char *);
  10. Prototype void UnloadGroups(char *);
  11. Prototype void CreateNewsrc(char *);
  12. Prototype void RangeAdd(Range **, short, short);
  13. Prototype void RangeDel(Range **, short, short);
  14. Prototype int  NextInRange(Range *, short);
  15. Prototype int  NextNotInRange(Range *, short);
  16.  
  17. Prototype void ClearGroupCache(NGroup *);
  18. Prototype FNode **FindFNCache(FNode **, long);
  19. Prototype void AddFNCache(FNode **, long, char *);
  20.  
  21. Prototype NGroup *PrevGroup(NGroup *);
  22. Prototype NGroup *LastGroup(void);
  23.  
  24. Local void  cns_tag(char *, char *, FILE *);
  25. Local char  *fgetstring(FILE *);
  26. Local Range *ReadRange(FILE *);
  27. Local void  WriteRange(FILE *, Range *);
  28. Local void  FreeRange(Range *);
  29. Local void  PrintRange(Range *);
  30. Local long  GetMaxArtNo(char *);
  31. Local void  ClearGroupChain(FNode *);
  32. Local void  CreateFNCache(FNode ***);
  33.  
  34. static FNode    *FreeFNBase;
  35.  
  36. extern NGroup *GBase;
  37.  
  38. /*
  39.  *  LoadGroups()
  40.  *
  41.  *  Load the newsrc file for the specified user and check for new groups
  42.  */
  43.  
  44. void
  45. LoadGroups(user)
  46. char *user;
  47. {
  48.     FILE *fi;
  49.     char buf[64];
  50.     NGroup *ng;
  51.     NGroup **png = &GBase;
  52.  
  53.     sprintf(buf, "%s.dnewsrc", user);
  54.     if (fi = openlib(buf)) {
  55.     short c;
  56.     while ((c = fgetc(fi)) != EOF) {
  57.         switch(c) {
  58.         case '\n':
  59.         continue;
  60.         case 'y':
  61.         case 'n':
  62.         ng = malloc(sizeof(NGroup));
  63.         setmem(ng, sizeof(NGroup), 0);
  64.         if (c == 'y')
  65.             ng->Enabled = 1;
  66.         ng->Name = fgetstring(fi);
  67.         ng->RList= ReadRange(fi);
  68.         ng->MList= ReadRange(fi);
  69.         ng->KList= ReadRange(fi);
  70.         CreateFNCache(&ng->IdBase);
  71.         CreateFNCache(&ng->RefBase);
  72.         CreateFNCache(&ng->SubBase);
  73.  
  74.         ng->CurNo = NextNotInRange(ng->RList, 0);
  75.         ng->MaxNo = GetMaxArtNo(ng->Name);
  76.         if (ng->CurNo > ng->MaxNo)
  77.             ng->CurNo = ng->MaxNo;
  78.  
  79.         while (ng->CurNo < ng->MaxNo && !FileExists(FileForArticle(ng, ng->CurNo))) {
  80.             RangeAdd(&ng->RList, ng->CurNo, ng->CurNo);
  81.             ng->CurNo = NextNotInRange(ng->RList, ng->CurNo);
  82.         }
  83.  
  84.         *png = ng;
  85.         png = &ng->Next;
  86.         break;
  87.         default:
  88.         puts("dnewsrc format error");
  89.         break;
  90.         }
  91.  
  92.         /*
  93.          *    skip to next newline.
  94.          */
  95.  
  96.         while ((c = fgetc(fi)) != EOF && c != '\n');
  97.     }
  98.     *png = NULL;
  99.     fclose(fi);
  100.     }
  101. }
  102.  
  103. void
  104. UnloadGroups(user)
  105. char *user;
  106. {
  107.     FILE *fi;
  108.     char buf[64];
  109.     NGroup *grp;
  110.     NGroup *gnext;
  111.  
  112.     sprintf(buf, "%s.dnewsrc", user);
  113.     fi = openlib_write(buf);
  114.     if (fi == NULL)
  115.     printf("Unable to open %s\n", buf);
  116.     for (grp = GBase; grp; grp = gnext) {
  117.     gnext = grp->Next;
  118.  
  119.     if (fi) {
  120.         if (grp->Enabled)
  121.         fputc('y', fi);
  122.         else
  123.         fputc('n', fi);
  124.         fprintf(fi, " %-20s ", grp->Name);
  125.         WriteRange(fi, grp->RList);
  126.         fputc(' ', fi);
  127.         WriteRange(fi, grp->MList);
  128.         fputc(' ', fi);
  129.         WriteRange(fi, grp->KList);
  130.         fputc('\n', fi);
  131.     }
  132.     free(grp->Name);
  133.     FreeRange(grp->RList);
  134.     FreeRange(grp->MList);
  135.     FreeRange(grp->KList);
  136.     free(grp);
  137.     }
  138.     if (fi)
  139.     fclose(fi);
  140.     GBase = NULL;
  141. }
  142.  
  143. /*
  144.  *  Create a new Newsrc file for a user
  145.  */
  146.  
  147. void
  148. CreateNewsrc(user)
  149. char *user;
  150. {
  151.     char buf[64];
  152.     FILE *fi;
  153.  
  154.     sprintf(buf, "%s.dnewsrc", user);
  155.     if (fi = openlib_write(buf)) {
  156.     ScanNewsDirs(cns_tag, fi);
  157.     fclose(fi);
  158.     }
  159. }
  160.  
  161. static void
  162. cns_tag(path, tail, fi)
  163. char *path;
  164. char *tail;
  165. FILE *fi;
  166. {
  167.     FILE *fj;
  168.  
  169.     sprintf(TmpBuf, "%s/.next", path);
  170.     if (fj = fopen(TmpBuf, "r")) {
  171.     int artno;
  172.     if (fscanf(fj, "%d", &artno) == 1) {
  173.         artno -= 50;
  174.         if (artno < 0)
  175.         artno = 0;
  176.         fprintf(fi, "y %-20s 0-%d - -\n", tail, artno);
  177.         printf("Adding %s\n", tail);
  178.     }
  179.     fclose(fj);
  180.     }
  181. }
  182.  
  183. /*
  184.  *  support
  185.  */
  186.  
  187. static char *
  188. fgetstring(fi)
  189. FILE *fi;
  190. {
  191.     char buf[128];
  192.     short i = 0;
  193.     short c;
  194.  
  195.     while ((c = fgetc(fi)) == ' ' || c == 9);
  196.     while (c != EOF && c != ' ' && c != 9 && i < sizeof(buf) - 1) {
  197.     buf[i++] = c;
  198.     c = fgetc(fi);
  199.     }
  200.     buf[i] = 0;
  201.     if (c != EOF)
  202.     ungetc(c, fi);
  203.     return(strdup(buf));
  204. }
  205.  
  206. static Range *
  207. ReadRange(fi)
  208. FILE *fi;
  209. {
  210.     Range *rb;
  211.     Range **rp = &rb;
  212.     short c;
  213.     short is, ie;
  214.  
  215.     while ((c = fgetc(fi)) == ' ' || c == 9);
  216.     if (c == '-')       /*  no range    */
  217.     return(NULL);
  218.     while (c != EOF) {
  219.     is = 0;
  220.     while (c >= '0' && c <= '9') {
  221.         is = is * 10 + c - '0';
  222.         c = getc(fi);
  223.     }
  224.     if (c == '-') {
  225.         ie = 0;
  226.         c = getc(fi);
  227.         while (c >= '0' && c <= '9') {
  228.         ie = ie * 10 + c - '0';
  229.         c = getc(fi);
  230.         }
  231.     } else {
  232.         ie = is;
  233.     }
  234.     {
  235.         Range *r = malloc(sizeof(Range));
  236.         r->SNo = is;
  237.         r->ENo = ie;
  238.         *rp = r;
  239.         rp = &r->Next;
  240.     }
  241.     if (c != ',')
  242.         break;
  243.     c = fgetc(fi);
  244.     }
  245.     if (c != EOF)
  246.     ungetc(c, fi);
  247.     *rp = NULL;
  248.     return(rb);
  249. }
  250.  
  251. static void
  252. WriteRange(fi, r)
  253. FILE *fi;
  254. Range *r;
  255. {
  256.     short first = 1;
  257.  
  258.     if (r == NULL) {
  259.     fputc('-', fi);
  260.     return;
  261.     }
  262.     while (r) {
  263.     if (!first)
  264.         putc(',', fi);
  265.     if (r->SNo == r->ENo)
  266.         fprintf(fi, "%d", r->SNo);
  267.     else
  268.         fprintf(fi, "%d-%d", r->SNo, r->ENo);
  269.     first = 0;
  270.     r = r->Next;
  271.     }
  272. }
  273.  
  274. void
  275. RangeAdd(rp, sno, eno)
  276. Range **rp;
  277. short sno;
  278. short eno;
  279. {
  280.     Range *r;
  281.     Range *rn;
  282.  
  283.     for (r = *rp; r; r = *rp) {
  284.     if (eno < r->SNo - 1) {     /*  insert before   */
  285.         rn = malloc(sizeof(Range));
  286.         *rp = rn;
  287.         rn->Next = r;
  288.         rn->SNo = sno;
  289.         rn->ENo = eno;
  290.         return;
  291.     }
  292.     if (sno <= r->ENo + 1) {     /*  extend this ran */
  293.         if (sno < r->SNo)
  294.         r->SNo = sno;
  295.         if (eno > r->ENo)
  296.         r->ENo = eno;
  297.  
  298.         /*
  299.          *    delete/combine later rans that the new range overlaps
  300.          */
  301.         while ((rn = r->Next) && r->ENo >= rn->SNo - 1) {
  302.         if (r->ENo < rn->ENo)
  303.             r->ENo = rn->ENo;
  304.         r->Next = rn->Next;
  305.         free(rn);
  306.         }
  307.         return;
  308.     }
  309.     rp = &r->Next;
  310.     }
  311.     /*
  312.      *    Append to end
  313.      */
  314.     rn = malloc(sizeof(Range));
  315.     rn->Next = NULL;
  316.     rn->SNo = sno;
  317.     rn->ENo = eno;
  318.     *rp = rn;
  319. }
  320.  
  321. void
  322. RangeDel(rp, sno, eno)
  323. Range **rp;
  324. short sno;
  325. short eno;
  326. {
  327.     Range *r;
  328.     Range *rn;
  329.  
  330.     for (r = *rp; r; r = *rp) {
  331.     if (sno <= r->ENo && eno >= r->SNo) {
  332.         if (sno <= r->SNo && eno >= r->ENo) {   /*  delete entirely */
  333.         *rp = r->Next;
  334.         free(r);
  335.         continue;
  336.         } else if (sno > r->SNo && eno < r->ENo) {  /*  split   */
  337.         rn = malloc(sizeof(Range));
  338.         rn->Next = r->Next;
  339.         r->Next = rn;
  340.         rn->ENo = r->ENo;
  341.         r->ENo = sno - 1;
  342.         rn->SNo = eno + 1;
  343.         break;
  344.         } else if (sno <= r->SNo) {              /*  else reduce an end */
  345.         r->SNo = eno + 1;
  346.         } else if (eno >= r->ENo) {
  347.         r->ENo = sno - 1;
  348.         }
  349.     } else {
  350.         if (eno < r->SNo)   /*  done    */
  351.         break;
  352.     }
  353.     rp = &r->Next;
  354.     }
  355. }
  356.  
  357. /*
  358.  *  Returns index after idx that is in the range
  359.  */
  360.  
  361. int
  362. NextInRange(r, idx)
  363. Range *r;
  364. short idx;
  365. {
  366.     while (r && idx >= r->ENo)
  367.     r = r->Next;
  368.     if (r) {
  369.     if (idx < r->SNo)
  370.         return(r->SNo);
  371.     return(idx + 1);
  372.     }
  373.     return(-1);
  374. }
  375.  
  376. /*
  377.  *  Returns index after idx that is not in the range
  378.  */
  379.  
  380. int
  381. NextNotInRange(r, idx)
  382. Range *r;
  383. short idx;
  384. {
  385.     while (r && idx >= r->ENo)
  386.     r = r->Next;
  387.     if (r) {
  388.     if (idx < r->SNo - 1)
  389.         return(idx + 1);
  390.     return(r->ENo + 1);
  391.     }
  392.     return(idx + 1);
  393. }
  394.  
  395. static void
  396. FreeRange(r)
  397. Range *r;
  398. {
  399.     Range *rn;
  400.  
  401.     while (r) {
  402.     rn = r->Next;
  403.     free(r);
  404.     r = rn;
  405.     }
  406. }
  407.  
  408.  
  409. /*
  410.  *  debugging
  411.  */
  412.  
  413. static void
  414. PrintRange(r)
  415. Range *r;
  416. {
  417.     WriteRange(stdout, r);
  418.     puts("");
  419. }
  420.  
  421. static long
  422. GetMaxArtNo(group)
  423. char *group;
  424. {
  425.     FILE *fi;
  426.     int max = 0;
  427.  
  428.     sprintf(TmpBuf, "%s/.next", MakeConfigPath(UUNEWS, group));
  429.     if (fi = fopen(TmpBuf, "r")) {
  430.     fscanf(fi, "%d", &max);
  431.     fclose(fi);
  432.     }
  433.     return(max);
  434. }
  435.  
  436. /*
  437.  *  References: and Message-ID: cache
  438.  */
  439.  
  440. void
  441. ClearGroupCache(grp)
  442. NGroup *grp;
  443. {
  444.     FNode **fn;
  445.     short i;
  446.  
  447.     if (grp->IdBase) {
  448.     for (fn = grp->IdBase, i = 0; i < FNHASHSIZE; ++i, ++fn) {
  449.         ClearGroupChain(*fn);
  450.         *fn = NULL;
  451.     }
  452.     }
  453.  
  454.     if (grp->RefBase) {
  455.     for (fn = grp->RefBase, i = 0; i < FNHASHSIZE; ++i, ++fn) {
  456.         ClearGroupChain(*fn);
  457.         *fn = NULL;
  458.     }
  459.     }
  460.  
  461.     if (grp->SubBase) {
  462.     for (fn = grp->SubBase, i = 0; i < FNHASHSIZE; ++i, ++fn) {
  463.         ClearGroupChain(*fn);
  464.         *fn = NULL;
  465.     }
  466.     }
  467. }
  468.  
  469. void
  470. ClearGroupChain(fn)
  471. FNode *fn;
  472. {
  473.     FNode *fnext;
  474.  
  475.     while (fn) {
  476.     fnext = fn->Next;
  477.     if (fn->Id)
  478.         free(fn->Id);
  479.     free(fn);
  480.     fn = fnext;
  481.     }
  482. }
  483.  
  484. void
  485. CreateFNCache(pht)
  486. FNode ***pht;
  487. {
  488.     if (*pht == NULL) {
  489.     *pht = malloc(FNHASHSIZE * sizeof(FNode *));
  490.     setmem(*pht, FNHASHSIZE * sizeof(FNode *), 0);
  491.     }
  492. }
  493.  
  494. FNode **
  495. FindFNCache(htab, msgno)
  496. FNode **htab;
  497. {
  498.     FNode **pfn = htab + (msgno & FNHASHMASK);
  499.     FNode *fn;
  500.  
  501.     if (htab == NULL)
  502.     return(NULL);
  503.     while (fn = *pfn) {
  504.     if (fn->MsgNo == msgno)
  505.         break;
  506.     pfn = &fn->Next;
  507.     }
  508.     return(pfn);
  509. }
  510.  
  511. void
  512. AddFNCache(pfn, msgno, id)
  513. FNode **pfn;
  514. long msgno;
  515. char *id;
  516. {
  517.     FNode *fn = malloc(sizeof(FNode));
  518.  
  519.     if (fn) {
  520.     *pfn = fn;
  521.     fn->MsgNo = msgno;
  522.     fn->Id = id;
  523.     fn->Next = NULL;
  524.     }
  525. }
  526.  
  527. NGroup *
  528. PrevGroup(grp)
  529. NGroup *grp;
  530. {
  531.     NGroup *gp2;
  532.  
  533.     for (gp2 = GBase; gp2 && gp2->Next != grp; gp2 = gp2->Next);
  534.     return(gp2);
  535. }
  536.  
  537. NGroup *
  538. LastGroup()
  539. {
  540.     NGroup *grp;
  541.  
  542.     for (grp = GBase; grp && grp->Next; grp = grp->Next);
  543.     return(grp);
  544. }
  545.  
  546.